package com.unis.controller.excelimport;

import com.unis.service.excelimport.UserTableInfoService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.iterators.ObjectGraphIterator;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.*;

@Component
public class ScheduledTask {
    @Autowired
    private UserTableInfoService userTableInfoService;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    public List<List<Map<String, Object>>> getTask(String taskType, String taskBatch, String task_schedule) throws Exception {
        Map<String, String> paramMapAll = new HashMap<>();
        paramMapAll.put("isOpenTask", "1");
        paramMapAll.put("taskSchedule", "0");
        List<Map<String, Object>> list = userTableInfoService.queryValidTaskData(paramMapAll);
        List<List<Map<String, Object>>> totalList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(list)){
            Set<Object> set = new HashSet<>();
            for (Map<String, Object> listBatch:list){
                set.add(listBatch.get("TASK_BATCH"));
            }
            int batchCount = set.size();
            for (int i = 0; i < batchCount; i++){
                Map<String, Object> paramMap = new HashMap<>();
                Map<String, Object> dataMap = new HashMap<>();
                dataMap.put("STATE", "1");
                dataMap.put("TASK_BATCH", String.valueOf(i+1));
                dataMap.put("IS_OPEN_TASK", "1");
                dataMap.put("TASK_SCHEDULE", "0");
                paramMap.put("dataMap", dataMap);
                paramMap.put("ordercol", "STATEMENT_ORDER");
                paramMap.put("order", "asc");
                paramMap.put("table_name", "SQL_SCRIPT_INFO_TAB");
                List<Map<String, Object>> ls = userTableInfoService.queryTableDatas(paramMap);
                totalList.add(ls);
            }
        }
        return totalList;
    }

    public void runcContenTask(List<Map<String, Object>> list) {
        try {
            if (CollectionUtils.isNotEmpty(list)){
                for (Map<String, Object> map:list){
                    if (StringUtils.isNotBlank(String.valueOf(map.get("SQL_STATEMENT")))){
                        try {
                            Map<String, Object> beforeMap = new HashMap<>();
                            beforeMap.put("setCol", "task_schedule");
                            beforeMap.put("taskScheduleValue", "1");
                            beforeMap.put("id", map.get("ID"));
                            userTableInfoService.updateSqlTaskSchedule(beforeMap);
                            String sql = String.valueOf(map.get("SQL_STATEMENT"));
                            jdbcTemplate.execute(sql);
                            Map<String, Object> afterMap = new HashMap<>();
                            afterMap.put("setCol", "task_schedule");
                            afterMap.put("taskScheduleValue", "2");
                            afterMap.put("id", map.get("ID"));
                            userTableInfoService.updateSqlTaskSchedule(afterMap);
                            Map<String, Object> sucessMap = new HashMap<>();
                            sucessMap.put("setCol", "fail_cause");
                            sucessMap.put("taskScheduleValue", "成功");
                            sucessMap.put("id", map.get("ID"));
                            userTableInfoService.updateSqlTaskSchedule(sucessMap);
                            /*记录执行时间*/
                            Map<String, Object> exeTimeSucessMap = new HashMap<>();
                            exeTimeSucessMap.put("setCol", "task_execution_time");
                            exeTimeSucessMap.put("taskScheduleValue", new Date());
                            exeTimeSucessMap.put("id", map.get("ID"));
                            userTableInfoService.updateSqlTaskSchedule(exeTimeSucessMap);
                            /*记录执行成功次数*/
                            int currentNum = Integer.valueOf("null".equals(String.valueOf(map.get("SUCCESS_NUM")))?"0":String.valueOf(map.get("SUCCESS_NUM")));
                            Map<String, Object> exeSuccessNumMap = new HashMap<>();
                            exeSuccessNumMap.put("setCol", "success_num");
                            exeSuccessNumMap.put("taskScheduleValue", (currentNum+1));
                            exeSuccessNumMap.put("id", map.get("ID"));
                            userTableInfoService.updateSqlTaskSchedule(exeSuccessNumMap);
                        }catch (Exception e){
                            Map<String, Object> erroMap = new HashMap<>();
                            erroMap.put("setCol", "task_schedule");
                            erroMap.put("taskScheduleValue", "3");
                            erroMap.put("id", map.get("ID"));
                            userTableInfoService.updateSqlTaskSchedule(erroMap);
                            Map<String, Object> causeMap = new HashMap<>();
                            causeMap.put("setCol", "fail_cause");
                            causeMap.put("taskScheduleValue", e.getCause().getMessage());
                            causeMap.put("id", map.get("ID"));
                            userTableInfoService.updateSqlTaskSchedule(causeMap);
                            /*记录执行时间*/
                            Map<String, Object> exeTimeFaildMap = new HashMap<>();
                            exeTimeFaildMap.put("setCol", "task_execution_time");
                            exeTimeFaildMap.put("taskScheduleValue", new Date());
                            exeTimeFaildMap.put("id", map.get("ID"));
                            userTableInfoService.updateSqlTaskSchedule(exeTimeFaildMap);
                        }
                    }
                }
            }
        } catch (Exception e) {

        }
    }

    public List<Map<String, Object>> getResetTask(String taskType, String taskBatch, String task_schedule) throws Exception {
        Map<String, Object> paramMapAll = new HashMap<>();
        Map<String, Object> dataMapAll = new HashMap<>();
        dataMapAll.put("STATE", "1");
        dataMapAll.put("TASK_TYPE", taskType);
        dataMapAll.put("TASK_BATCH", taskBatch);
        dataMapAll.put("IS_OPEN_TASK", "1");
        paramMapAll.put("dataMap", dataMapAll);
        paramMapAll.put("ordercol", "STATEMENT_ORDER");
        paramMapAll.put("order", "asc");
        paramMapAll.put("table_name", "SQL_SCRIPT_INFO_TAB");
        List<Map<String, Object>> list = userTableInfoService.queryTableDatas(paramMapAll);
        return list;
    }

    @Scheduled(cron = "0 */1 * * * ?")
    public void runTask() throws Exception{
        /*ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();*/
        List<Map<String, Object>> resetList = getResetTask(null,null,null);
        if (CollectionUtils.isNotEmpty(resetList)){
            for (Map<String, Object> reMap:resetList) {
                Long TASK_EXECUTION_TIME = ((Date)reMap.get("TASK_EXECUTION_TIME")).getTime();
                Long minutes = (new Date().getTime() - TASK_EXECUTION_TIME)/(1000*60);
                Long setminutes = Long.valueOf((String.valueOf(reMap.get("TASK_INTERVAL"))));
                if (minutes >= setminutes){
                    Map<String, Object> resetSchedulMap = new HashMap<>();
                    resetSchedulMap.put("setCol", "task_schedule");
                    resetSchedulMap.put("taskScheduleValue", "0");
                    resetSchedulMap.put("id", reMap.get("ID"));
                    userTableInfoService.updateSqlTaskSchedule(resetSchedulMap);
                    Map<String, Object> resetCauselMap = new HashMap<>();
                    resetCauselMap.put("setCol", "fail_cause");
                    resetCauselMap.put("taskScheduleValue", "");
                    resetCauselMap.put("id", reMap.get("ID"));
                    userTableInfoService.updateSqlTaskSchedule(resetCauselMap);
                }
            }
        }
        List<List<Map<String, Object>>> lists = getTask(null,null,null);
        if (CollectionUtils.isNotEmpty(lists)){
            ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(lists.size());
            for (List<Map<String, Object>> cList:lists){
                Future<Boolean> future = (Future<Boolean>) newFixedThreadPool.submit(new Runnable() {
                    public void run() {
                        runcContenTask(cList);
                    }
                });
                Boolean taskResult = null;
                String failReason = null;
                try {
                    // 等待计算结果，最长等待timeout秒，timeout秒后中止任务
                    taskResult = (Boolean) future.get(30, TimeUnit.MINUTES);
                } catch (InterruptedException e) {
                    failReason = "主线程在等待计算结果时被中断！";
                } catch (ExecutionException e) {
                    failReason = "主线程等待计算结果，但计算抛出异常！";
                } catch (TimeoutException e) {
                    failReason = "主线程等待计算结果超时，因此中断任务线程！";
                    newFixedThreadPool.shutdownNow();
                }
            }
            newFixedThreadPool.shutdown();
        }
    }
}
